﻿// Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml.Linq;

// add these namespaces
using MyTravelPostModel;
using System.Data.Objects;
using System.Collections.Generic;

namespace ObjectServices_ASPNET_CS
{
    public partial class TravelPage : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // check the post back
            if (IsPostBack)
                return;

            // get the blog id from the page request.
            int blogID = 0;
            int.TryParse(Request.Params["BlogID"], out blogID);
            ViewState["BlogID"] = blogID;

            // create a short lived context
            using (MyTravelEntities travelEntities = new MyTravelEntities())
            {                   
                // get the last blog post and span in the Blog and Person information.
                BlogPost post = null;

                // make sure there is the blog post.
                if (travelEntities.BlogPosts.Any(b => b.Blog.BlogID == blogID))
                {
                    post = (from bp in travelEntities.BlogPosts.Include("Blog.Person")
                                                               .Include("Comments")
                                   where bp.Blog.BlogID == blogID
                                   orderby bp.BlogDate descending
                                   select bp).First();
                }   

                if (null != post)
                {
                    // fill in the new text.
                    labelBlogTitle.Text = post.BlogTitle;
                    labelSeries.Text = post.Blog.SeriesTitle;
                    labelPerson.Text = post.Blog.Person.Name;
                    blogEntry.Text = post.BlogEntry;

                    // call the methods to update the comments.
                    UpdatePostComments(travelEntities, post);

                    // not set all the people in the dropdown list
                    dropdownPersons.DataTextField = "Name";
                    dropdownPersons.DataSource = travelEntities.People;
                    dropdownPersons.DataBind();

                    // setup the viewstate that we need in the submit button
                    ViewState["BlogPost"] = post;
                    ViewState["People"] = travelEntities.People.ToList();
                }
            }
        }

        // this takes care of the refresh action that could cause problems.
        private void ReloadPage()
        {
            int blogID = (int)ViewState["BlogID"];
            Response.Redirect("TravelPage.aspx?BlogID=" + blogID);
        }

        // on submit, we need to add a comment that's associated to the blog post.
        protected void buttonSubmitComment_Click(object sender, EventArgs e)
        {
            // create a short lived context and send back the travel blogs.
            using (MyTravelEntities travelEntities = new MyTravelEntities())
            {
                BlogPost post = (BlogPost)ViewState["BlogPost"];
                List<Person> peopleList = (List<Person>)ViewState["People"];

                // get the person from the people list
                Person person = peopleList[dropdownPersons.SelectedIndex];

                // attach the post and the person that wrote the blog.
                travelEntities.Attach(post);
                
                // created a new comment and attach the travel entities.
                // NOTE:  You don't have to call add because the entity gets
                // added from the post.
                Comment newComment = new Comment();
                newComment.CommentText = textComment.Text;
                newComment.BlogPost = post;
                newComment.PersonReference.EntityKey = person.EntityKey;

                travelEntities.SaveChanges();

                // clear the text.
                textComment.Text = "";

                // call the methods to update the comments on the field
                UpdatePostComments(travelEntities, post);
            }

            // ReloadPage takes care of refresh actions.
            ReloadPage();
        }

        private void UpdatePostComments(MyTravelEntities travelEntities, BlogPost post)
        {
            // because the query is no tracking, we need to include the people of the
            // comments.
            var comments = from c in travelEntities.Comments
                           where c.BlogPost.BlogPostID == post.BlogPostID
                           select new
                           {
                               Author = c.Person.Name,
                               WhatISaid = c.CommentText
                           };

            gridComments.DataSource = comments;
            gridComments.DataBind();
        }

        protected void ButtonUpdated_Click(object sender, EventArgs e)
        {
            // create a short lived context and send back the travel blogs.
            using (MyTravelEntities travelEntities = new MyTravelEntities())
            {
                // get the comments to update.
                int commentIndex = gridComments.SelectedIndex;
                if (commentIndex > -1)
                {
                    // get the blog post and attach.
                    // because this is binary, the comments are also serialized
                    BlogPost post = (BlogPost)ViewState["BlogPost"];
                    travelEntities.Attach(post);

                    // get the comment and update the text.
                    Comment toUpdate = post.Comments.ElementAt(commentIndex);

                    toUpdate.CommentText += "*";

                    try
                    {
                        travelEntities.SaveChanges();
                    }
                    catch (OptimisticConcurrencyException opt)
                    {
                        // catching this exception allows you to 
                        // refresh entities with either store/client wins
                        // project the entities into this failed entities.
                        var failedEntities = from e1 in opt.StateEntries.ToList()
                                             select new { e1.Entity };

                        // Note: in future you should be able to just pass the opt.StateEntities in to refresh.
                        travelEntities.Refresh(RefreshMode.ClientWins, failedEntities.ToList());
                        travelEntities.SaveChanges();
                    }

                    UpdatePostComments(travelEntities, post);
                }

                ReloadPage();
            }
        }

        protected void ButtonDeleted_Click(object sender, EventArgs e)
        {
            // create a short lived context and send back the travel blogs.
            using (MyTravelEntities travelEntities = new MyTravelEntities())
            {
                // get the comment to delete
                int commentIndex = gridComments.SelectedIndex;
                if (commentIndex > -1)
                {
                    // get the blog post and attach.
                    // because this is binary, the comments are also serialized
                    BlogPost post = (BlogPost)ViewState["BlogPost"];
                    travelEntities.Attach(post);

                    // get the comment, and delete.
                    Comment toDelete = post.Comments.ElementAt(commentIndex);

                    // delete the object
                    travelEntities.DeleteObject(toDelete);

                    try
                    {
                        travelEntities.SaveChanges();
                    }
                    catch (OptimisticConcurrencyException opt)
                    {
                        // catching this exception allows you to 
                        // refresh entities with either store/client wins
                        // project the entities into this failed entities.
                        var failedEntities = from e1 in opt.StateEntries.ToList()
                                             select new { e1.Entity };

                        // Note: in future you should be able to just pass the opt.StateEntities in to refresh.
                        travelEntities.Refresh(RefreshMode.ClientWins, failedEntities.ToList());
                        travelEntities.SaveChanges();
                    }

                    UpdatePostComments(travelEntities, post);
                }

                ReloadPage();
            }
        }
    }
}
